From 316d4504213689a9e81f010ad230a4ce86b17803 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 27 Mar 2013 10:22:14 +0100 Subject: [PATCH] Handle non-baseline supporting subclasses overriding baseline supporting classes If a subclass (say a child of GtkButton) overrides the non-baseline size request methods we need to call these, rather than the new get_height_and_baseline_for_width method. In order to handle this we make the default for this method to be NULL, and instead check at runtime which method to call. If any non-baseline vfunc has changed in a class but the baseline one hasn't, then we can't use the baseline one. --- gtk/gtksizerequest.c | 59 +++++++++++++++++++++++++++++++++++++----- gtk/gtkwidget.c | 30 +++------------------ gtk/gtkwidgetprivate.h | 1 + 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index 4e47d88420..26a7efc769 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -93,6 +93,46 @@ get_vfunc_name (GtkOrientation orientation, return for_size < 0 ? "get_preferred_height" : "get_preferred_height_for_width"; } +static gboolean +widget_class_has_baseline_support (GtkWidgetClass *widget_class) +{ + GtkWidgetClass *parent_class; + + if (widget_class->get_preferred_height_and_baseline_for_width == NULL) + return FALSE; + + /* This is kinda hacky, but for backwards compatibility reasons we have to handle the case + where a class previously did not support get_preferred_height_and_baseline_for_width, + but then gained support for it, and a subclass of it overrides the previous non-baseline + methods. If this happens we need to call the overridden (non-baseline supporting) versions + on the subclass, rather than the inherited but not overriddent new get_preferred_height_and_baseline_for_width. + */ + + /* Loop over all parent classes that inherit the same get_preferred_height_and_baseline_for_width */ + parent_class = g_type_class_peek_parent (widget_class); + while (parent_class != NULL && + parent_class->get_preferred_height_and_baseline_for_width == widget_class->get_preferred_height_and_baseline_for_width) + { + if (parent_class->get_preferred_height != widget_class->get_preferred_height || + parent_class->get_preferred_height_for_width != widget_class->get_preferred_height_for_width) + return FALSE; + + parent_class = g_type_class_peek_parent (parent_class); + } + + return TRUE; +} + +gboolean +_gtk_widget_has_baseline_support (GtkWidget *widget) +{ + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_GET_CLASS (widget); + + return widget_class_has_baseline_support (widget_class); +} + static void gtk_widget_query_size_for_orientation (GtkWidget *widget, GtkOrientation orientation, @@ -170,9 +210,12 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, if (for_size < 0) { push_recursion_check (widget, orientation, for_size); - widget_class->get_preferred_height_and_baseline_for_width (widget, -1, - &min_size, &nat_size, - &min_baseline, &nat_baseline); + if (widget_class_has_baseline_support (widget_class)) + widget_class->get_preferred_height_and_baseline_for_width (widget, -1, + &min_size, &nat_size, + &min_baseline, &nat_baseline); + else + widget_class->get_preferred_height (widget, &min_size, &nat_size); pop_recursion_check (widget, orientation); } else @@ -194,9 +237,13 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, &adjusted_for_size); push_recursion_check (widget, orientation, for_size); - widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, minimum_width), - &min_size, &nat_size, - &min_baseline, &nat_baseline); + if (widget_class_has_baseline_support (widget_class)) + widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, minimum_width), + &min_size, &nat_size, + &min_baseline, &nat_baseline); + else + widget_class->get_preferred_height_for_width (widget, MAX (adjusted_for_size, minimum_width), + &min_size, &nat_size); pop_recursion_check (widget, orientation); } } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 4ba5b71c1a..f2f239f050 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -799,12 +799,6 @@ static void gtk_widget_real_get_width (GtkWidget static void gtk_widget_real_get_height (GtkWidget *widget, gint *minimum_size, gint *natural_size); -static void gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget, - gint width, - gint *minimum_height, - gint *natural_height, - gint *minimum_baseline, - gint *natural_baseline); static void gtk_widget_queue_tooltip_query (GtkWidget *widget); @@ -1124,7 +1118,7 @@ gtk_widget_class_init (GtkWidgetClass *klass) klass->get_preferred_height = gtk_widget_real_get_height; klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height; klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width; - klass->get_preferred_height_and_baseline_for_width = gtk_widget_real_get_preferred_height_and_baseline_for_width; + klass->get_preferred_height_and_baseline_for_width = NULL; klass->state_changed = NULL; klass->state_flags_changed = gtk_widget_real_state_flags_changed; klass->parent_set = NULL; @@ -5417,7 +5411,8 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget, /* Never pass a baseline to a child unless it requested it. This means containers don't have to manually check for this. */ if (baseline != -1 && - gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE) + (gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE || + !_gtk_widget_has_baseline_support (widget))) baseline = -1; alloc_needed = priv->alloc_needed; @@ -13619,25 +13614,6 @@ gtk_widget_real_get_width_for_height (GtkWidget *widget, GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width); } -static void -gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget, - gint width, - gint *minimum_height, - gint *natural_height, - gint *minimum_baseline, - gint *natural_baseline) -{ - if (width == -1) - GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height); - else - GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, width, minimum_height, natural_height); - - if (minimum_baseline) - *minimum_baseline = -1; - if (natural_baseline) - *natural_baseline = -1; -} - /** * gtk_widget_get_halign: * @widget: a #GtkWidget diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 79278134eb..6ec03fd9b4 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -77,6 +77,7 @@ void _gtk_widget_get_preferred_size_for_size (GtkWidget *widget, gint size, gint *minimum, gint *natural); +gboolean _gtk_widget_has_baseline_support (GtkWidget *widget); gboolean _gtk_widget_get_translation_to_window (GtkWidget *widget, GdkWindow *window, -- 2.30.2